package com.kaifamiao.tcp;

import java.io.*;
import java.net.*;
import java.nio.file.*;

public class FileClient4 {
    public final static int PORT = 12345;
    public final static String SERVER = "127.0.0.1";
    public final static String FOLDER_PATH = "/Users/linrui/a/";

    public static void main(String[] args) throws IOException, InterruptedException {
        WatchService watcher = FileSystems.getDefault().newWatchService();
        Path dir = Paths.get(FOLDER_PATH);
        dir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE,
                StandardWatchEventKinds.ENTRY_DELETE,
                StandardWatchEventKinds.ENTRY_MODIFY);

        System.out.println("Watching path: " + dir);

        while (true) {
            WatchKey key;
            try {
                key = watcher.take();
            } catch (InterruptedException ex) {
                return;
            }

            for (WatchEvent<?> event : key.pollEvents()) {
                WatchEvent.Kind<?> kind = event.kind();

                if (kind == StandardWatchEventKinds.OVERFLOW) {
                    continue;
                }

                WatchEvent<Path> ev = (WatchEvent<Path>) event;
                Path fileName = ev.context();
                System.out.println(kind.name() + ": " + fileName);

                // Only send changed file or folder
                try (Socket socket = new Socket(SERVER, PORT)) {
                    System.out.println("Connected to server!");

                    DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
                    File changedFile = dir.resolve(fileName).toFile();
                    if (changedFile.isDirectory()) {
                        sendDirectory(changedFile, dos, fileName.toString() + "/");
                    } else {
                        sendFile(changedFile, dos, fileName.toString());
                    }

                    // Signifies end of transfer
                    dos.writeBoolean(false);
                    dos.writeUTF("END");

                    dos.close();
                    System.out.println("Transfer completed!");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            boolean valid = key.reset();
            if (!valid) {
                break;
            }
        }
    }

    public static void sendDirectory(File folder, DataOutputStream dos, String path) throws IOException {
        dos.writeBoolean(true);
        dos.writeUTF(path);
        for (File fileEntry : folder.listFiles()) {
            if (fileEntry.isDirectory()) {
                sendDirectory(fileEntry, dos, path + fileEntry.getName() + "/");
            } else {
                sendFile(fileEntry, dos, path + fileEntry.getName());
            }
        }
    }

    public static void sendFile(File file, DataOutputStream dos, String path) throws IOException {
        dos.writeBoolean(false);
        dos.writeUTF(path);
        dos.writeLong(file.length());
        FileInputStream fis = new FileInputStream(file);
        byte[] buffer = new byte[4096];
        int read;
        while ((read = fis.read(buffer)) > 0) {
            dos.write(buffer, 0, read);
        }
        fis.close();
    }
}
